{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Benchmark comparing sklearn and GPU TSNE\n",
    "\n",
    "GPU TSNE source:  https://github.com/georgedimitriadis/t_sne_bhcuda\n",
    "\n",
    "Sklearn TSNE: http://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sklearn version: 0.19.1\n",
      "Numpy version: 1.14.5\n"
     ]
    }
   ],
   "source": [
    "import t_sne_bhcuda.t_sne_bhcuda.bhtsne_cuda as tsne_bhcuda\n",
    "import numpy as np\n",
    "import os\n",
    "from utils import plot_tsne\n",
    "import sklearn\n",
    "\n",
    "print(\"Sklearn version: {}\".format(sklearn.__version__))\n",
    "print(\"Numpy version: {}\".format(np.__version__))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "perplexity = 10.0\n",
    "theta = 0.5\n",
    "learning_rate = 200.0\n",
    "iterations = 2000\n",
    "gpu_mem = 0.8\n",
    "files_dir='tsne_results'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "data_for_tsne = np.random.rand(1000, 1000) # type: numpy.float64"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### TSNE with GPU"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Read the 1000 x 1000 data matrix successfully!\n",
      "Using current time as random seed...\n",
      "Using no_dims = 2, perplexity = 10.000000, learning rate = 200.000000, and theta = 0.500000\n",
      "Computing input similarities...\n",
      "\n",
      "Device Name = Tesla K80\n",
      "multiProcessorCount: 13\n",
      "totalGlobalMem (in MB): 11441.187500\n",
      "totalGlobalMem (in GB): 11.173035\n",
      "sharedMemPerBlock (in bytes): 49152\n",
      "Maximum number of threads per block: 1024\n",
      "Maximum size of each dimension of a block: 1024 x 1024 x 64\n",
      "Maximum sizes of each dimension of a grid: 2147483647 x 65535 x 65535\n",
      "Compute capability of the device = 3.7\n",
      "canMapHostMemory: TRUE\n",
      "deviceOverlap: TRUE\n",
      "GPU memory usage: used = 71.000000 MB, free = 11370.187500 MB, total = 11441.187500 MB\n",
      "\n",
      "GPU iteration = 0, distance elements calculated = 1000000\n",
      "GPU memory usage: used = 82.625000 MB, free = 11358.562500 MB, total = 11441.187500 MB\n",
      "Time spent in calculating all distances in GPU: 0.298834\n",
      "Building tree...\n",
      " - Building tree and finding perplexities, point 0 of 1000\n",
      "Time spent building tree and finding perplexities: 0.500906\n",
      "Input similarities computed in 1.06 seconds (sparsity = 0.048582)\n",
      "\n",
      "Learning embedding...\n",
      "Iteration 50: error is 155.078074 (50 iterations in 0.66 seconds)\n",
      "Iteration 100: error is 144.523697 (50 iterations in 0.59 seconds)\n",
      "Iteration 150: error is 143.061462 (50 iterations in 0.63 seconds)\n",
      "Iteration 200: error is 141.476110 (50 iterations in 0.64 seconds)\n",
      "Iteration 250: error is 10.037677 (50 iterations in 0.59 seconds)\n",
      "Iteration 300: error is 6.278916 (50 iterations in 0.52 seconds)\n",
      "Iteration 350: error is 4.970615 (50 iterations in 0.50 seconds)\n",
      "Iteration 400: error is 4.914033 (50 iterations in 0.49 seconds)\n",
      "Iteration 450: error is 4.845600 (50 iterations in 0.51 seconds)\n",
      "Iteration 500: error is 4.687777 (50 iterations in 0.51 seconds)\n",
      "Iteration 550: error is 3.958540 (50 iterations in 0.50 seconds)\n",
      "Iteration 600: error is 3.742951 (50 iterations in 0.47 seconds)\n",
      "Iteration 650: error is 3.707510 (50 iterations in 0.42 seconds)\n",
      "Iteration 700: error is 3.706029 (50 iterations in 0.43 seconds)\n",
      "Iteration 750: error is 3.705951 (50 iterations in 0.44 seconds)\n",
      "Iteration 800: error is 3.704772 (50 iterations in 0.44 seconds)\n",
      "Iteration 850: error is 3.704908 (50 iterations in 0.44 seconds)\n",
      "Iteration 900: error is 3.704176 (50 iterations in 0.44 seconds)\n",
      "Iteration 950: error is 3.704399 (50 iterations in 0.44 seconds)\n",
      "Iteration 1000: error is 3.704678 (50 iterations in 0.44 seconds)\n",
      "Iteration 1050: error is 3.704785 (50 iterations in 0.44 seconds)\n",
      "Iteration 1100: error is 3.704121 (50 iterations in 0.45 seconds)\n",
      "Iteration 1150: error is 3.704714 (50 iterations in 0.44 seconds)\n",
      "Iteration 1200: error is 3.704248 (50 iterations in 0.44 seconds)\n",
      "Iteration 1250: error is 3.703553 (50 iterations in 0.44 seconds)\n",
      "Iteration 1300: error is 3.703678 (50 iterations in 0.44 seconds)\n",
      "Iteration 1350: error is 3.703734 (50 iterations in 0.44 seconds)\n",
      "Iteration 1400: error is 3.703910 (50 iterations in 0.44 seconds)\n",
      "Iteration 1450: error is 3.703901 (50 iterations in 0.44 seconds)\n",
      "Iteration 1500: error is 3.703906 (50 iterations in 0.44 seconds)\n",
      "Iteration 1550: error is 3.704067 (50 iterations in 0.44 seconds)\n",
      "Iteration 1600: error is 3.704536 (50 iterations in 0.44 seconds)\n",
      "Iteration 1650: error is 3.704506 (50 iterations in 0.44 seconds)\n",
      "Iteration 1700: error is 3.704066 (50 iterations in 0.44 seconds)\n",
      "Iteration 1750: error is 3.703581 (50 iterations in 0.44 seconds)\n",
      "Iteration 1800: error is 3.704473 (50 iterations in 0.45 seconds)\n",
      "Iteration 1850: error is 3.705080 (50 iterations in 0.46 seconds)\n",
      "Iteration 1900: error is 3.704567 (50 iterations in 0.45 seconds)\n",
      "Iteration 1950: error is 3.704398 (50 iterations in 0.44 seconds)\n",
      "Iteration 1999: error is 3.704011 (50 iterations in 0.44 seconds)\n",
      "Fitting performed in 18.95 seconds.\n",
      "Wrote the 1000 x 2 data matrix successfully!\n",
      "\n",
      "T-sne required 20.622339 seconds (0.343706 minutes) to run\n",
      "TSNE return code: 0\n",
      "CPU times: user 132 ms, sys: 56 ms, total: 188 ms\n",
      "Wall time: 20.8 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "t_sne_result_gpu = tsne_bhcuda.t_sne(samples=data_for_tsne, use_scikit=False, files_dir=files_dir,\n",
    "                        no_dims=2, perplexity=perplexity, eta=learning_rate, theta=theta,\n",
    "                        iterations=iterations, gpu_mem=gpu_mem, randseed=-1, verbose=2)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1000, 2)\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXYAAAD8CAYAAABjAo9vAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJztnW2QVcd55/99LwdxByUaiNm1fS2EVuUCmyAxK8rCy9ZWUBzjjSxljCwTRdpN7VZZlapNbcDylJGlGPDiQGoqllJJPkSOU7spscqAUCZgnEV2iVQ2xCgGz2DCCtZWZJCuVTFZGCViBnFnpvfDTA9nzu3u031O93m7z6/KLs3l3nP6vPTTTz+vjHMOgiAIojrU8h4AQRAE4RYS7ARBEBWDBDtBEETFIMFOEARRMUiwEwRBVAwS7ARBEBWDBDtBEETFIMFOEARRMUiwEwRBVIwFeZz0Pe95D1+xYkUepyYIgigtp06d+kfO+bK47+Ui2FesWIGTJ0/mcWqCIIjSwhi7YPI9MsUQBEFUDBLsBEEQFYMEO0EQRMUgwU4QBFExSLATBEFUDBLsBEEQFSOXcEeCiGN4pIXBo+fx47EJvL+3gYFNK9Hf18x7WPMowxiJ7oQEO1E4hkdaeOLFM5hoTwEAWmMTeOLFMwBQGMFZhjES3QuZYojCMXj0/JzAFEy0pzB49LzX8w6PtLBh78u4ffsRbNj7MoZHWoUbI0GYQIKdKBw/Hpuw+twFQgNvjU2A44YGrhLuqrG0xia0CwJBZAEJdqJwvL+3If28tyfwdk5TDVxo9VxzLN2CkBc2uxGi/JBgJwrHwKaVCOqs4/N3rk16E0gmu4SwVq+jaCYZ290IUX7IeUoUjv6+JnYeOouxifa8z9vTHINHz3txTr6/tyEV2OHdg0yrV+HbbBSOxtm4ahmOnbukjM7R7UbI0VtNSGMnCklUqAt8CcyBTSvRCOrzPmsEdQxsWpno3CpzUlpk2vdzJy5qtfE8fBZEvpBg7wLKZl8dHmmh0xAzgy+BCQA3LbgxHZb0BNizec08jVZ17uhYowuCS0x2DVFTkGrcPu8lkS8k2CtOGe2rg0fPS52TDPAiMMU9Cu8SrrWnO76n0uofWb8czd4GGIBmb6NjQXCJqZYd/p7JboSoFmRjrzhltK+qhBeHn+Qf03sk/jvPbFOVL0D2PUERxk1kCwn2ihF1rKmEQJHtq6px1xnD8EjLuUAqkw1646pl2HfiojbcUnwvTH9fkwR5F0GCvULI0twZIBUCRbavDmxaOe86BFOcO0vbDy+ANcYwxTvvUvQe5V1GYHikhYOnWrFCHQCOnbvkfTxEcSEbe0mROURlJgWOTucew4xQKqojtb+viQfvlgtKFzHiUb+DTKjLbNBJywi4cl4XJdySKD6ksZcQleaomvQcM069qAZf1MJVQjNVkVZoqQRknTFMc660QScx2bjU8vMMt6RKluWCBHsJUWmOdYVJodnbwPHt92LD3pc7bNdFdKTGaaZphZZKQE5zjtf33if9t+GRltZkoxJ8SZzXqmP19gS4Mi6P7w/jOuIlbxMUYQ8J9hKiEkxTnKMR1OcJkvAkL4uTUBf14UJomWSZhhGCTWWy2bhqmVLw2d5znRCVnH52DDUsXXyTN21atTjtPHSWtPiCQjb2EqISQCKGWhVTXYZEFV1yUp0xJzHitnHdOtPNns1rcOzcJaVWbnvPdRr+24ps3GvtaRzffi9e33sfjm+/N7OoobGJdqnyI7oJEuwlRCaYhEN08Oh5DGxaKZ3kZUhU0SUn/c5n7nIitPr7mtoFMIrOdNPf19Rq5bb3XHesrBdmk0qWYYpW/KybIVNMCQknnNg4RMuQqOIjOUllszY9nsp0U5uNq9eZdkzvuRijSoiK30Wd5L4W5qhJyJSimfW6FRLsJUUIJluHaNETVVRCsplQKzV1/OmiPuLi6h+8u4mDp1pKgRt3z+OEqDhWlguzzoHd7G1g/Pqk1JFbJLNeN0OmmJKT1CFa1MJgrs1FJrHncfV0hOmmzjqt/xPtKRw7d8nKtGMyRkH0WP19zTl7+sCmlRg8et7LM1S9PwzA8e33Ysf9qwtv1utmSGMvObYRHkCxw9dca6UmC59JSGJ/XxPbhkaVx0qzE4oTojJ8P8O498r1c6I4ebekFuyMsVsB/AmA9wKYBvAs5/x30x6XMCOJ3bXIhcFcT3CThU/Xv3TD3pfnxqKKI09rfkiyOPt+hqr3auOqZfPuiQsBXGRFo6y4MMVMAnicc/4hAOsB/BfG2IcdHJcwwDbCA9ALsjzxUWLYxLSjq7MeHss71yY7Wva5MD8kMT/5zkkQZR2E+anOGP718ltw8FTLeYhj0lINhJrUgp1z/hbn/Huz//3PAF4FQMtshoTtriZxzDpBlqet3ccEN1n4VOGj0QiV9jTH4oULnNdeT7I4+w59FGUdRFLWFOf4m9cuexHAZUmcKxNObeyMsRUA+gC84vK4hFsGNq3EtqHRDsHFgVzNMb4muIn9+6YFtTmhtUSTuv/2RBs7H1g9Zy4SQs2FcLc5hu/QR1VBORlpn08SUxShx1lUDGPsZgAHAWzlnP+T5N8fY4ydZIydvHSJSormSX9f09skTUMembGq7klLegLp929pBIXoSJVEy7chy4JjZUicKxtONHbGWIAZob6Pc/6i7Duc82cBPAsA69atM01mIwxI4nBsFlBLyjIBR6Ay/9y0oCatu8MYcnM8y56zKmomLSotOmqisnk+cYliFBXjjtQaO2OMAfg6gFc5519NPyTChqQOxyJqSb61UBkqzfTtibZ0LGMKE43vnU7WvWtd93eVjX/r0Cj6vvzSXFcsn/Vuug0XGvsGAP8BwBnGmAj0/SLn/JsOjk3EkDTsrahakomt2WVIZFw5gOhxRRkH2fd9knWIquv3Q5WEdWW8TaGNHkgt2Dnnf43OJj1ERqRxOBa9vIAM1zHPtuafrM1FYhHLo3ety/dDN86i5FBUCco8LTndFlFgo7k+NXwGz7/yBqY4R50xPHzPrdjdv2bed2w10yx3Ok8Nn4ltXF2W56xrrA5QaKNrSLCXnDgNsmqp2qY7lKeGz+C5Exfn/p7ifO5vmXC3uSdZ7HSGR1qxQj2osdJEjmxctWze84hSlgWqLJBgLzk6DVJmthg4cBq7Dp/F2Hi7FII+ujDd0gjmhSYKooLh+VfekB7v+Vfe6BDseSNbfHUlfOewNIDmucgfO6cOcc7baV9FSLBXAJUGKTNbtKf5XPJNUvt0VgJCtjAFdYagxtCeviH2ZIJB1sZO93le2DYmD9Oe4sa26bzrsehMLb4jn7oRKttbYUzsluGUcJNSvlmG3UkXpimOmxfFp/XLSuzqPs8LXWNyE0xt03nXY9G1cySh7h7S2CtMnMNK8OOxCWONzkfYnWoHoOy1Od7GyJc+rj3mw/fcKrXpPnzPrc7G5wKbxuQyTG3TeddjySP5rJshwV5hVJ1/ory/t2EssHUCIokA1C0oaSJ+hB09LiomjmhkSloThqnPoBmytesWZ5VgjJ7HV8lhU4qaN1FVGM/B5rhu3Tp+8uTJzM/bjYQn+C2NAFevT6I9Nd8+vWfzGmlRMGDGP/f63vvm/pa14gNmCmdda093aGRx9lPV8YRgk2l5Wdlkh0dayvvS7G1Yp/Ob9hGNXqPunst2LrLzBDUGMEifPQnX8sAYO8U5Xxf3PbKxV5xwqvbojo9j8NN3Se3TpgW4Bjat7KhJHtQZOFfXUNGh2wHISgw8eHfTWzu4KLrIlCQmDF0LPHFHTcsKN4I6dty/2vg8vkoOE8WETDFdhiqCxsoGKqn3KzMnAPECUGVuuaURzOvU8/SWtQCQaWSHbuxJTBi643GodwG2Zgxd/RsfJYeJ4kGC3YKqJfuEMRUeg0fPzws1BGa0wTpj0lDCOAEoW1CCGsPV65Nzi4UQ4IuCmnPHrQ5dhcMkTr802Zc2SVG6xXLghdNz5pjW2AQGXjg9d/woZX/fyz7+NJApxpCsq+vlgUmFvbgojjAyjT8aUgmgw9xy86IF82zBwIwAVzW/8BXZoeqs9Mj65Ynr0kSPF8aVI1NlumlPTXfc1/YUx67DZzuOUfb3vezjTwsJdkNUUSOP7z/dNS8LoG+r9+DdTa0NVzbZtg2NYuvQTFHQp7esxfHt9ypL46qoMZbqGaji92U2/qe3rE2cuSqOJ2vi4TL0T1X++Op1uX1ftmDaxr2b5EBkSd5x+3lDphhDdJpq2dL006Brq3fs3CVtpIiu3ZpJmGNvI8C7k9Mdx5jiPLGtPS5+P2ldGFUBMnE832YC2bjFAmqCTdx73lmtMvKO288b0tgN0W2TRZp+N2z50rTVi/t3oVGpTAk7H1iNPZvXSLMyJ9pT2Hmo06QQhw/NThQgCzeCfu7ERawIabN5NJbobcjb/ck+v0XxXdk8yFI7Nt0Z5NFmsUiQYDckzj4aRphoirItdU0z4aRZuCD+dWspwhyFWae/r4lpRe7F2ETb+l770OxUBciAfBf+nQ+snolnDxHUGHY+MD9scnikhavXJzt+r6om6VM7DgvytbtewsALp43s5kXsEJYlZIoxRGhUj+8/bVRISnynCNtS1yRND393cjr22EIb15lAdNElthEyPurZx70fWTSW0Jl6jCKfpjqv4eZFC6Rj9tUTIGrikYXUqu5lt2e6kmC3QLwUptX3BBPtKew6fLYyL1lcqeA01xknFIdHWhiXaJMCWy3RRw0TVehnGJ+2XhO/QZKxqZzavurA6BK6wqjGW8YOYa4gwW5JVKjJ0vRlXBlvzyuXK6JBmiUV8rJJ48KJxmaPI74fVxIhiq2W6EOzUxUgSzNOG9IWarPVwH1px6aLX7fYzW0gwZ6AqFALC5+agbYGyKNBshbu4XH39gTgfCY7MenEjBMoG+5YiuOvXdYeg2MmemPw6HlsXLUMB0+1tFvxMCotMW4X4Vqz292/BgdPvYmJttz0FNTltmpXkTJpbd5JNHAf2rFJddJuspvbQILdAeGX2rTQU5g8mvlGxxmOZY7LSFQRJ1D2ffajeORr34kV7mIMcVpvGNXOR7eLAMy0zCQCd8/mO5UFxBYv7LRVJ93tyMaW1uZdFPu0Kiv55kULuiK0OA1U3dED0cl29d3JWG0zWkXRN6qKgWFU1QNtjxmugZJkdxOHrtKiakyqmPjwv4tokXAavuDR9ctjE5VWbD8i/Vz2rE3uXRSZEtEI6njw7ua8nY74PJwwVpZ0+7KMMytMqzuSxu4BmakmTovP0k741PAZowYcqhR+FSaNtcP/7kKox5lfVNcZt9COTbSxdWgUDJ01zwDguRMXse62pVoh07TQnJOYT1Smr2PnLmHP5jVKgZjGF5K1oI3uhgePnse2odFMzl3mRYUEewaEt7atsYkOYeHTThjNgPxXy3rwg59cNf592JEZR9wWXhXlYBJFIjDZiicxh6nQjSrOfKYyJYxfn8SK7UfmrruZsBFGXMlj1dhUC4LwbehMUnllmGZ97iJm09pAgj0jZJqHb01AZEAKpji3EuoArF7muOtSCaJpzvHMlrVGwnjwobtix2IaJpeWOGekKoJKCPBwrgMA1GsMUzFNuk1MWb0980semz4HMZbwM487ny//kMyc6auyp+y99dECMktIsOdAdML7qouty4A0xfRlNtFwdE696K5GxqOGVRWzrAcStaMv6Qmw4/7Vc+MML+gb9r6sNQFNTXMs6QmUuxETU1ZQZ3g7Elo7cOD03L/rmocIRN4FACPTmev7LXuXVKQ9t+q9VSkGZak1Q4I9B3xs82RahwsbNmD2MptoOHE2+LAQVBXRMkG1gNiYfEyQHenK+Ixt/uSFyx3jNbmPPQsXKB3WcaasOmPSGP/2NMfAgVEsqMc3xw5fx85DZ42+79o/ZLPjSntu1XubtL9AUSDBngNptnkyAQ7IOwsxBriQYyYvs4nzzyaMbnf/msTlcVULyIN3N7UhlDUGTDuS++I84WswicvWCf+4Wvg6YdieBtrTduapOAcz4Mc/ZKoVuzi3zT0tU8y8E8HOGPtjAJ8E8BPO+c+6OGaVSZpAotL0VZ2FeoIaxhVJMmE++C8WY/z6dCrHrmnsdBZp3roFRCfYv/qZtcrY8yTsi0TOqEoeh9EtorqdSBY+hShRs1NSosqKypG8pCdAz8IFTn1TqnvaDNnauzkq5r8D+H0Af+LoeJUmaQKJStNXTeqJ9rRRtuebV67NxTgPj7Sw89DZOW1tUWBWANRXvZCkqBaQJRqh0d/XxMkLl7HvxEUnwp1jfuRM3PHj7pfqHvsS6kt6Alxrq2P9eySJVrbIlJWgxhDU55uVRPNu14JV997mGWqZFidleznnfwUgPp2QAGBXUjRcttQk9jzM+3sb2PfZj+KZLWvnSuCqapmHa2eHqzBeGW8blZnt71OX2i0SO+5fjaAeKV1bZ9hx/0wy0u7+NXg6dL96GwGW9ARz19R59/REd2Hh4wM3nofJ/VLdY1UZ5Sg2YxeCdM9mtTnMhSNRpqy0pzkWL1yQybtk8t6Wsc2es8xTxtgKAN9QmWIYY48BeAwAli9ffveFCxecnLesmIQ8msZjy7Ioo5mGgtu3H5FqiyIbMkkGZNlIE24aDSGNI4v7ZvKeCB/DN06/1WE7F/927Nwl6T3x+U7EvY9ZonovijQnCpd5yjl/FsCzwExJgazOW2ZMogNEZyHx/ThhFWcG6oaWYmns/MIZKiJ2BIsX1jt6imZlipL5FDauWiYV1Lv711gvbD7NbD5quSdZuHWRamWcExQVkwOm4Y66F4cBHS+tibCKm6S+miZUCVXETp4p6HGLlTDpJRmbz6JgrheNpKHEuki1Ms6JrhLsRan9YBruqPPYJ90Cxk3SpBOtKPc2T7KI+EnC8EhrXiGzJNU7fV2b60UjaSixTit/WpIVXfTQR1fhjs8D+DkA72GMvQlgB+f86y6O7Yq4ldyVYDI5junWztcWWDdJk0y04ZEWBg6cRns6JDgO2Jf9DR+vLIuE7VjzuLZdh892JC61pzg+t3+0EFEeLheNpGYT06zoMryTQBeV7dU5QFQC1NYTryqjGj2Oaix1xjDNudNWc1mwdtdL0mSW3kaA0R3mZX8B83tYBGzHmte1qcoHRxGliot2n21I6ugsy3tXOOdp3uhWclcFf0yPI1tIAHUD7CK9WDJUGYommYtRylR8yXasRb+2sYm2sgmJyhlbBKKdwIIam9s9Ama73DJq5Tq6RrDrtlquvN6640Q173B4WZZV84qO6h62xiawYe/LcxNU10i7NTYxrySurwmqG6us3HFe0RW9jcB4kZ1oT2HnobPzwmej3axUPXvz2F3qOoEBdruQMihRpnSNYNfZq1UVBW293qrFo7cn6LDvHzzVmtvm3a7YKhc5nCqMqiaNJBdqHjZt3YCQ049jnj3/iRfP4MDJi/MybMO7H1VRrrToxhrVfHXJZb6jK3Y+sHqeDyQOk0Ug2rP3wMmL+JvXLmfeyzcuJDicbNdNOMk8LQO6DDObTFAdquNwDuUWHFBP7N6ewOr8vghnv27Y+3JHxp3KTSP7XBxrxfYj2DY0Oi+bb9vQKFb8TKPjHoZpT/EOATXRnootm/DciYvGmYJx1yuQPe/wmHYeOouBF05rhXpQkze2dkl/XxODD901L5s2mn2bBnH/o487mtHsgzjlJ4sxFJGu0dgB9VbLlX1NdZxtQ6PS74uXcmDTSjx+4PS8JgsA8M61SasORmmxqRwJ3LheVQu4aKp7dNscFQQcwPHXLmPxwrqyJV0aVKatqI32nWuTHTsCoFPzFH9vVTxfE823Pc1x8sLlTAqjRdPkdx0+22G6cH3fwyY0H9doUjFTZRqrMl0TFZMXwyMtPL7/tLS2s/DUD4+0lMIhq7TlaKwzMFNDZfHCBVIBFW1QnSYaKEtEETDb2uxJGmabwgA8vWVtLoInupj7ej5pIkx0tnvTshtFjHBJgmlUDAl2j+heunDvTlWLMyC7mhl9X37Junn1j0LjMnGcqeqClAHdc1AtbDZVF01L0vp2UPpcfG2UFF0z8qiQDn9Xt+OoQr0jCncsACrHDpv9v2jvSxlZpS3bCnWG+Y2uTSIKfGqEvtE9B5UJLlz+OI4r4/Pb2W0dGsWBkxex77MfnftOFg2WdU1KDp5qpSoRrHv24QVL9IaVdYMCOiPGouV1VbvfsgQjuKBrnKdZEHW6qV5kDihf2jAMcO5YM3UMxiFqjdugczYWnR+/PYGnhs8o/72/r4nj2+/F63vvw/Ht96K/rzlXnC0px1+7jDueODL3jHRx8K5QBRns7l/T8fkzofLDJghlIEq0LO7YRDt2fqiEdH9fUzkmF0qSq/njG9LYHSHTptI4ohiARwybN5siG+O22VBAm1hnga0GpKpCKCslWzQ4l7e70yGu9/MHTmMyYc+9KT7jnFVpoYB7TVQXZCD73MTGDXQ2HhHY9DgV6IS0r1IcWeyYXEGC3RGyl5OjM8qgEdSxKKhJTR+ykgIu2XW4szkxx0wLt39j0GkpShINSCYcdvevwVPDZzo6Cwnn7dsTbWn244qfaViPOS3Pv/KGVTy8uN5o5A3nmLuuq+9OplrYsjLX6ez7pmYn2SJka56L28maRrnZ+iuKnjkchgS7I1RaE8f8LvIP3t3EutuWZl6XYnikpbSjcwB/YykgXVe3292/ButuW5qojvaTf3amoxY6MOOgnuLcWYNqQO8P0aHzQejswnEwABtXLUv0WxvitNXo4qUKCIguQjrzlgzTnWyczyeJ9l2muuwk2B2hcgwy3BAGU5zj4KkW1t22FHs2r8k0/TrODmsjrnyl6SdJ6Y46zmRx+KqaJ4C9qUzWWjAt/X3NjsxZUzhmTERHvv+Wl56ggjj7fvgeP71lLYBOE01UGRgeaVl1owLchYUm0b7LVJedwh0dIQt5U9nY8wi7chVq+KOM25X5xDQGOsyj65c7L00guOcr38I//PP1xL8X2qyP8ekqREZDO8XuE9CbQ1RVQVW4nDdJWvIVoQIkhTtmjMyup7Id5rF1043H1Mn76PrlTseUNypb7MkLlzvs/QCw4Y6l3oQ6ACyop4sYEv6SdbctdS5odAldKs1XRAepsBHqrk1/SbTvMlWAJMHukKgpQRXymMfWTVUquLcR4JN3vU8bo1xjwK/c409TzROZ+ae/r5nI3p8WFwu+KvIkLba+hbTX8uj65V7LBCeNnClLBUgS7B7x2QTYFp22MTzSwjdOvzU3ziU9gVd7bRKSZlwm/Z3JBHadBeoqgcvHjlBVD0ilyZsoL6K8Q5TFC+velQhfkTNFgQS7R4q2dZMJK5nd8Fq7WKVOZREMW4dGsfPQWW2tbZ9xx66OPS8dXuKXrTFYR/XIhGpaAWWTkWqqvOy4f7W0PtFXPpXNztBH5ExRoMzTLieLbMY0iCJqMjPR2EQbW4dG0ffll6QZgD6vzcWxReE1oQnLrB2LFtSweKG57V0mVKOZnUJA2WRN2mSkmjoT+/uaGPz0XfN+O/jpu6TKRx7ZnkWfGzpIY/dIGVb8IsfmypKWZFwZb0vvq89rc3FsWZPpKOPtadTYjCYb/q6IgDHxBbhKrLHNSE1zTIHpHEqzI1H9tshzIw4S7B6Jm1B52u/EuVViJe/Y3OGRlpFQF8gElc+4YxfHNi28Ns2Bn164AItvUld/FO+R0CazWuB8o5pDj+8/jW1Do3O5CUPffWNu4ZvrtIV4BUq3cJQpbj0KmWI8EtcDNe32OCnhc8tguNEgIesiR8MjLaz+0v/C1qFR67j76P121RlLhs9jy3h7ot1RZAwwM7OoBFEZBJRqDk1xPne9z5242LHzaU9x7Dp8Nvb4OuUr62fsEhLsHrmlIW9txwGp3Vi0U/ONruhSOKZdOClVNmzXiNR6WXkAE6KCSmUXNtHi4my6SY+dFJVDVPUehe3AZRZQaRYfkx2RTvnK+hm7hEwxHtFln6vigscm2t7beOm24LJRqWzYrvn8gdOJf6sSVDb23+GRVkcxK1EBc+vQaEcphSxjmlUOUdV7FH7GRYvOskGVf+GKOHNLWeLWo5Bg94ht8wrBzkNnvb5MSeKls6hil7S0bdraNU8Nn9HWLAnvYPJyfkfPt/NQZ6XOMLLdSxkFVHRR0nUbi9Kr2DGHKVKuiUtIsHvEtq+mwLfWnlQL8ulsS2rqEaGA24ZG5+yiNolLeS5wqgSdKKJxhOmYfQumrJ3+0UJv0Xc3qDNMTXGEsy+CGjNqdFLm3YwOEuweSVriFfCTFi7o72sq66Ho8OVsE5M1CVevT+Hq9RlBZ6pRJyn+FcbVArfj/tVG5Xo3rlpm3JO2zpj38s95hvCqBLHsM9PxlHU3o8OJYGeMfQLA7wKoA/gjzvleF8ctMyYaqC6r0Hco2rFzl6yEuk8tMM6sYEOcRj080sLn9o+mqtFeY8zJjqq/r4nPDY1CledbZ8DCBTWr0rYP33Or9/LPeTeb0MXTEzOkjophjNUB/AGAfw/gwwAeZox9OO1xy45JdppOofcdima7cPjSAodHWs7b4qmuTWR6pm28McU5tg2NYoWDTEjdUKY5MGFZ3uHI999KPBYVIkpoxfYjSjNQWZuUVxUX4Y4fAfBDzvnfc86vA/hTAL/k4LilxkRw6ia1b+eNzcLR7G14E+qf25+sc5AO1bUNHj1v1ETchKhDNalw1z2HJCNN6rBXEZfzIPDQf4RIgQvB3gTwRujvN2c/62rSaNy9jcD7tlIW26z7rmuEwHDZtg7Qm4x8mbfS1A+RPYciyUjTRtOcAx/6zb9A35dfyrymC9GJC8Euew87pitj7DHG2EnG2MlLly45OG2xGdi0EkE9forKEkdMvPlp6e9r4gNLFhl/1zVJOtPHEZdA4tO8lXTRkCXBZN/TTI3NdU20p3FlvJ15JjXRiQvn6ZsAbg39/QEAP45+iXP+LIBngZnWeA7OW2iEcNl1+KxyeyyaW/tsKADIw9P+4NgP8IOfXI39bSPwk5zsWnvWtU1LGtpoQ5pFI+oMtG0ZF8YkdtvqeIYhmTKydqoSN3Ah2L8L4IOMsdsBtAD8MoBfcXDc0iMmrHDaRe27orl11uFpNlEhezaR0998AAAdXklEQVTf6WVcrppKADNbRpX5RXXvXeIyYuip4TOJhbpp7LYpLhzbouZQHrHhZW2S4YLU6hjnfBLArwM4CuBVAPs55/4LnpSMKYVg8V3fWWbyMBXqS3r82fptbPxxcKjNRSalcdPgsn6IqGiZlMGHOmuZpxnLEy+e0UZumZKHWSbPIntFwEkcO+f8mwC+6eJYVWTw6HllrDLgN2Y96bGDGsOO+/3Z+sOJJmk196bGDOI6SiSKyvyTBF0Z5ThcL8KufSAmZhmXGnbW8fa6seexc6DM0wyIE64+nXpJTB69jUDbcs4V4vhpskDTmEGStJ0Lo7NnJ5nMSRfhuodFOMlYGkENi4K6cjHVHdN1Rqsu3t61aUg3dgC5ZOqSYE+B6eSNE64+Y9Zt68I8s2VtpnbINJph2uJfaYS6zp6dVEglWYRdNR6Pvsu3NAKlfV2Udha1kMLPYXikhW2KWvo6Bcalhj080ppXfjqKa+Ea10Ivj0xdEuwJsZm8A5tWKmuC9AQ17wWUgPl1NMbGr0trni9eWM/cuZRMM6x7czhHBYJNCzpBUiFlswj3NgKM7vi4wRXFI3uXa5pIXQ7gR3vvk/6bypykc3ADbrs8mZi0XArXJGP3XTKkKwW7C5uXzeQVRbeiNT+COsNveYo6iZ4/2h8yz+7wYWy11LRaehx89hyyd8P0nEmFlDi+SWGwtx2WYUjjYI+iukaOG2U2bHa1NcZw+/YjVvPUVGgmEa4y2RFX0z2P9nqVEuwmAtuVLc928u7uX2Ol9fmkSKVKbbRUXay6il6NScHVOaIk7ZUpOkiZnsMVtgJuSY/at6BbqON2tbL3QFRItZmnpspC+B6mkR0P3t3EwVMtZU33POq9l0qwx3meTQS2K1tekslbpPKgRRlLdJHp7QnwbnsK45HiV0knw84HVmPgwGm0IyrohjuW4nsX3/Yy4ZI0b7Ctm+NSMNjumnSO2riFWrerBfQNNUznqYmyEH4eaWXHsXOXsGfzGu3CQFExCuJuvqnAdmXLq2rnlTyQLTKuQsR0uxNfYWhJdkSDR88bmz8eXb/cqWDQ+YCibLhjqfbcJmGsqrkWfg9u337E6reqMYj7v3HVMmWGtwvZoVOU8lCiSiPY426+qcBOuk2OUiRzRhVxORl09bt9PS/bY5tqzP/ypxZid79bX0h/X1MZyRLm0fXLjc4trn3D3pcTzzVVKYNejRlINgYTspYdWeCnEIgH4m6+6uZGP3fZsb2/r4nj2+/F63vvw/Ht9zqNi92w92WqktdFmFR0/Omb6njlyV/wcn6dUG8EdTyzZa31gpJ0rg2PtPDOtUnpv71zbdL5fMhDdvimNBp73GppahopuqadV+uxbq6roSNcQEzEbcvit9Oew8QK81ONhanOo6OpmF9pWu0lnWuDR893+EQE7Wlu5Q8zea+rIjvClEawx918m5teFMehDJXJ6fH9pwH4Ee5597EsKtH7Ipx54UiNbUOjOHnhcirziGmtIJ+xzwObVnY4mYMaS1x/JipQn7ZIfIu7TtP78NTwmXl9fVXvtWvZUQQlqTSC3eTm2wrsIjyAKKqXdopzZ8I2et1X352ULibbhkbnnGquMhzjxlKEZyAwyYrlAPaduIh1t+mdijpMBZUrW274nvf2BOAc0pDQ9jTHzkMz9fxs51UaRSEuSkd2H6Lv0cZVy6TN2nVROWneu/DOLpzklpeSVBrBDrjVtNO8fD6Fke6lTpNiHZ7I71ybnNPMdBMoPCmujLcx8IKbXYOqPnrRdgqmDk2RfJN0zCY1z4M6c2LLjWqxcecdm2hbP5O0IcW6cEWZiUQ2l2VCXeB65xM9v+li4pNSCXaXJH35fJstVJqGwPaljI43TbXD9pSdfdNkPFEm2lPzQu9cLqDhBa5nYV1aVgG4sTupS2KpVSQVFjpHYZgFNeZkQdW9WypsBVPakOJoyGTYp7Fx1TIMHj2PbUOjc++EbC7rrtF1FIvJzq41NoEVsyGcvna/YbpWsCd9+UwWhKQa/fBICwdP6R1pti+l6/KrabUd0/FE46pbYxN4/EDyHUO0jIJKqAM3diemQh1ILix0jsIwE+1pPDV8JrUtP2ndM5vn7iIsUJXbIFOqbN7vuJo1SbCdEy53vypKE+7oGtMQpyhxC0KaAv9xQi9JaJXrbWdabSfNeKamObYOjSYKAbVtuNGe4tpCWGHShLzZ3I99Jy6mCvVLc+9FzRaTe+8rLFClVNWZ/EFFPxUF3VwL0yRzQux+fdG1gj3pyxe3IMSV8ATUceq6iZe0U4/LbacLO6+L8bTGJjBw4LSVkEtigprmiG1InraDks39CBfS8n2uKFOcGysq/X2dDbpdVOPUBRbI5vIj65fPG8PTlrH4pvkkMlliohP4jHKqpCnGxBSSNCY1LuxSp9EPj7Q6mluHbfSqLWyawlSy8QZ1hskpbrUtZwwY/HT61mu29eFViIgN3w6psJbPGMC52wqTtvcjjTCwKR2gY6I9hW37R7Hz0Fm8PdF2EqFmgm5+CFu7S3+MqS9NJ0tU2bfienzBuIumhpasW7eOnzx50suxZc65uPrdtjZx3fdVDzKoAZPTaqeOeDltx26CbLwmKeRRVDW4k47HRTNr0zGt3fVS6sbMvurA21R1XNITYORLyeuw9335JS/tAsW9Afwl8CSZ20lRzeOokhUnO4ZHWtIidEGdJVKUGGOnOOfrYr9XNcFu+kAErl8W1YM04Ud778ssrlunSahwXQt9eKSFxw+cxlSKVkamgl1UT0zTNQlwU9ZXhunzSNtgIy4qKQ29jQDvTk5r59LwSAs7D52dt8jaRIlkNT9u335E2TDk9dl3zlR2RK85TVSMqWCvnCnGNtrFddPb/r5mh7nFBOEAyiorNolJxHVop2oL+/h+s4gUXV1w1bmSPJswvuyipmaStA02xH344ovf7yiNLCOoM4DDSFGR7YjCc0ml9NhEiWQ1P0wie0xlRx6Z7pUT7CYPJLzq+0hiGEsgOGxC61wgXjRbm6vrZAvZSy/rNhUlqNs3cBbn0vXljMN19mc4TlvXp9Pl+cV9eGr4DJ5/5Y25+jcP33OrtBkMAOPFVoZoIK3bkdjkSGShtZvUj3HZzs81lRPscQ/EdCuaZgIlaUrczKH0Z39fM5EzzfeLu7t/DQ6eehMTCo1y8cI6vvKp5HbV/r6ZVoW2yTquKvlFsz+FwIwbi+tKgrv710ijRFT3VTdvGkEdi4KadDfEYJbFa/JemTo10wp/k+CKIpfxrZxgj3sgJgkyaSeQrZnD1YRN8jJvuGMpjr922eo8Wby4ezbfKb2HG+5Yin2f/Wjq44tWhTrTzOKFdQT1mjLyw5bhkRae/LMz2uQoFb2NADsf8JutKNC9R9EaM+F7A3QKf5NdiMDkvTJNEHSRHR5nQilys53KOU/jUDlFgJmX0NXWLjw5ZG2+BL2NAIzNmG/SnFvlyHnw7qayc4zgka99Rync6zU2z7npKwpBRlaOsizOk9RRnKVAB9IHE0TvpenO1TRKxMSpaRtAkYasi9h1bVRMHFk+dIFuMWkEdScROarrimpMuuOb2lyLUKCrbCQNM0wb3miL6/lhEu1jEyViMj4T4V9WujYqJo48tk8qzaXOmLOIHJV90qbSnK3NlTAnaSSOj5hzHa4dgq5zM0zmb5ztu8ilol3RdSUFfKU761CVL1CZZ5JMIhu7d/T41IqPECStoaTC9XwzOZ6uXEiaWk5lIpXGzhh7CMBOAB8C8BHOeT72FUuyjitVOXRV2ZdJJpFMk1E5rqKhn9Q9yT+9jSBR5mtvwzxW3wU+drSu51vc8eJS/F3mrRSVtKaYvwOwGcAfOhhLpVG9jK4mkexl3rhqGQ6eammP7zpBi5Cz84HV1hnJQY1h5wN2sfqCpOaGpDWUioZqvhU59twlqQQ75/xVAGCKspmEHteTSPYyxzk/u+VFz5vws26NTcwVFFORpnyDbBe2dWgUuw6fNXJS5pEpmRVFjj13Sdc5T4uG70kUd/xuedGLQPRZ+HLiqXI1roy3UzXflo1XnK8s2n2RY89dEhvuyBj7NoD3Sv7pSc75n89+5y8BfF5nY2eMPQbgMQBYvnz53RcuXEg65q7ElxBwUQStG6IMyoQuvFbQE9TwW5vvtHrGsvLP0ToyoplFmk5Pvinz++os3JFz/jEXA+KcPwvgWWAmjt3FMbsFnw5OnTlIFtcenrCySn3kfM2fWwwctePtaav2bLJdgKwjFcdMp6d1ty0t7POvsqlJQKaYAhLVKMavT3p1cMpMBB/+zb+YV/1vivO5wly7+9doa+64dr7mqWHpzl1EzW94pIWr1+ObYwN2hbdsfC6i01Pe96KbSZV5yhj7FIDfA7AMwBiAUc75prjf5Zl5WnRs6mUzAE9vWeu1c0yUOmP4nc/cZVTtr9nb6KgrcksjQHtqeq5eSlzKfJbNFWzODajroriuW2+DbZ39uGxMWdcvF8fNivDiK6tvU7bFh0oKlIwkXYWW9AS41tY3NrDFRDBEyyCkJagxDD4krxOSRwkIgaoMQF1T+0fgq/NV0loqKnT3MU0jlCyeTxxxSkqWdY9cYSrYuy7ztIiEs+FMaQR1cI7Yxtm2mGy5XXffaU+rO7ZnFY4Zzb595GvfUWqpJnXJ0z6HpBmSNtFMcc3Jdx0+m0ioFyXKJK6Sa9pnVGRIsOdEWJA8vv+0lbAUadSqbjpphF5eYY6qMavGU2PMWQkEmRC1LWUsI81zUCWO7Tp8Vvs7WTq9jCU9QWw1xSR1arIo0WGKyf2var4GOU9zILpFtOlMw4C5La7LkgQCVS15xoBH7lmOY+cuOWlCHUU1ZtV4xD0zjcKJqzHuowdomuegEjhXxtsYHmkprzWuM5bO9h29RzYU0axhUjZYdZ1FdIzbQBp7DqQRJOEXUVfsKCmyIkvPbFmL1/fch939a4w1QhuCmtokIMaj628at6WOM2v47GNqQ3gXV9Nkc8eZD/r7msqOXDpBFr1HcTCGzArpJSHuXVXNlSoUCiONPQeSCpKoTdRXXQ9dnK+qJs2R77/VsXU36Z7TE9SwcEEd24ZGMXj0vHT8/X1NDB49rzUNtMYm5jk7w9E2cfVwkrQyNMHmOdjs4kzGunHVMmnf2I2rlkm/n0jZ4MWIfFFh0vVJ9oyqUD+JBHsOqASJThCqmhHkkWwhO6eIbVdV1JNdbyOoYaI9PRcvL2qa/MGxH+Bbn/u5ed81WQzDgn9soo2BA6e1vxWf27Yy9IGNYK0b1GY6du6S1ee6+6uKAipD2Ykk86MK9ZNIsOeArvkAkG/tjTS2RdUkUglOVbPqH/zkKh752nfm9TbVadWqBbE9zbHr8NnYejhizCax+abULOvi2QgNkzHaCifVPRI7n26oryKoQv0ksrE7wqZZha5ZQH9fE8e334vX996H49vvzVyo+7Atiuu1qS0ejUpR2UuX9ARac8+V8TY2rloW64vo72ti2lKob7hjKXoC+RT6lXuWWx3LRmjUGUsc9qhzUgeS1UhksfpqTmMyb7JuBOPDd5U1lKDkgDyzI13iOxnINivyRxH7raq6oCoCRCAyQeN2IkmyNqOzR0QP2RbBkhbZqs14J2U1WVTvVzjRzabfLaBOyPKVbGQyb/KaW0WNiqGepxlSBWcL4N+2aHucaFifzNTzwS8eMTqvia3V1tYu7U51SyNRZUOVIxyQm4hk71dUCHLYlTkYUzinfdmWTeZNXnOr7IXCSLA7oArOFsC/bdE2+sQkPl1hpu84rwky4Xr56rtKX4CMNM9cJUy2KXYk0XPJhKAQ6iYad9a2ZdW9ao1N4PbtR7TvS9nmVtaQjd0BaRsAF6WZtG/bom0MvKuUb1WIn4yoj2PP5jtn6o4b4kMImr5faRWMrG3LunslfDyqO18z8DN0MyTYHZBmQhQpGULn1HV5fF2yURQXmpkqxM+E/r4mBj9917wx9zYCPLp+eWZC0PT9MlkAdEqE7+cfxWShV3kApzgvXdJQlpDz1BFJnS1ZVC+Mll6NK5WbBdH7dfXdSWlziLj78MjXvhNb18VXCdksHWwm54pzNBbRyR++riSSqAhVJLOEyvYWlOgE1cVmuxBGwyMtDLxwuiOyogbgq1vWFsZBZCp0ZALuwMmLWuFe1clv24M0zxLIJthGJQHFqfueFVS2t4DIzC4qG6IrW+3g0fPScLlpzIQJ5mnTD2NiBlCZrR5atxw/2nsfntmytvTxx6ao7gUAZR5EUht8Vj4gmWkmzrtRpqShLKGomAxRRS3I4o1dCaO4SVukHqVxIWZxoW++aucUkV2Hz1qHASaJevHZbzeKqg7RwVMtaQiqbJ4UNf48a0iwe0L2gqmErAhJ8/EymoQYTrSnsHVoFCcvXC50d3kTjbPs8ccmDI+0lAXRdM9aVcpCp0SoFtOtmqJtaZA9v3W3LZ1LuhJ1a2Rx+VkuQkWHBLsHVC+Yqnu8TxvnwKaVsZmZgnCz6iJShRoeLtCFgOoKhCXZ0eh2fFkJTtPFuiqJgi4gwe4B1Qu2KKh19Av1bQPu72vi5IXL0hKuMp47cRHrbltayImQROOsGsMjLa1WHlcgzHZHE7fjK5LgrEqioAvIeeoB1Ys0Nt7ONE5YsLt/DZ7Zstb4+9uGRrEi52QpGVnHWRcNsRPUYVNozQSTWHPxvuedaJc2UbBKkMbuAZ3JIC8bsI3mLnS+Itoou8GGrsKkZnt7yrz8gQlh841Kc39/b6MQ9m3a0d2ANHYPFLXs5+7+NXh0vV052Sp3ci8bJiaFq9fdNwsRZRZ04aQ6+3ZWdPuOLgxp7B4octjd7v410jZ2OrrRRllEfLXwM0X3Xqsc9FmPt5t3dGFIsHuiyC/YjvtXS7NRVXSjjTJrTOKvBzatxLahUW3qfSOoYcPel70pFKr3WtU+z6SNH+EeEuxdiKrJ79hEO1GyVLcmhaS57vBve3sCvHNtEu3pmTsver8KLThc20fnJ6kBmJzmc1pylnZuVTTOFOdd+37kCdWKIeZhOwllNV6AmU5CnEObUFJ0hkda2Hno7FzuwZKeAPfd+T4cO3cpUYei8HFtm2cHNYbBh+4CAOluq7cRgDFk2gEpjKrOS28jwLuT04UqPFZmqAgYkQk2hZuKMqFNFq+nhs8Yx/6HMRGiSYpdiWMDcru1yFyWzeYsCmWpirgtCmq5LTZVJJPWeIyxQQD3A7gO4DUA/4lzPpbmmES5sHGsTrSn8Pj+0zh54TKOnbuU+dY8qoEDM0Jy4IXTAG6YK4ZHWtiXQKgDZvcjqTNa9ztdtdAsfCQqx6qu+xOZaPyRSmNnjH0cwMuc80nG2G8DAOf8C3G/I429OiTVPsMENYabFy3A2Hg71QSX1Z3/5F3vM44CCje9TnpNeWrsqjjuPHdJqmtd0hPgWptMNLZkUraXc/4S53xy9s8TAD6Q5nhE+bBtdyejPc1xZbw9V35269AoHvnad6yOIerOhwX42EQbz524aBzaKZyNSYW6aa6C6p7pAkiCGsPAppXaHIkixnGrxss5co97rzLObOyMscMAhjjnz8V9lzT2ahHVlF3x6PrlxgXJXOwckiAcqLbOYZlZSNATzOhb47NNtIUjWpwDKGaOhAqZyUUVttltjTNsceY8ZYx9G8B7Jf/0JOf8z2e/8ySAdQA2c8UBGWOPAXgMAJYvX373hQsX4sZGlAwxgcPlVdNQZwyv7flFo+/evv1IotZqaagzht/5zF2JhapuMWoEdTx4dxNDf/vGXBgkcCM6psiC3ISid3MqKs6cp5zzj8Wc6FcBfBLAz6uE+uxxngXwLDCjscedlygfsuSVJKF9ApuFwWVWpumiNM15KgGrc4ZOtKew78TFjsWqPc2x89DZ0gt2quvil1Q2dsbYJwB8AcADnPNxN0MiqoTM7vvo+uVzjkAdNlmLA5tWIqinz3JsBHU8fM+tRn6DtNEmcb9XLS0y803ZKKI/oEqkzTz9fQA3AfgWm5mEJzjnv5Z6VESlUKWhx2nzD99zq9U5AMRGxURt4oDcXi269sgyQwE32qVMa+0milx2o+xQghKRK2G7vKDOGB6+59ZCdXLyFXOtcjw3gjpqTF6tcUlPgJEvfTz1uYnyQZmnBFEiZAsH0Fk+IKgzDH66/M5TIhmZZJ4SBOEGnVmiTKGNRDEgwU4QBYbs0EQSqIMSQRBExSDBThAEUTFIsBMEQVQMEuwEQRAVgwQ7QRBExSDBThAEUTFIsBMEQVQMimMniBJD7eUIGSTYCaKkRIuoiQ5QAEi4dzlkiiGIkjJ49Dy1lyOkkMZOECVF1ahD9jmZbLoL0tgJoqSoGnVEPxcmm9bYxFzD8CdePIPhkVYGoyTygAQ7QZSUgU0rOzo9yRqAkMmm+yBTDEGUFGFKiTOx6Ew2ZKKpJiTYCaLERMv6Do+0sGHvy/MEtarR9y2NgKJqKgqZYgiiIqhs6RtXLZOabBgDmWgqCgl2gqgIKlv6sXOXsGfzGjR7G2CYaeS9Z/MajEX6rApUphuiPJAphiAqgs6WLuvEFG0iLlBF2xDlgTR2gqgIpuGPAtOoGqJ8kGAniIpgK6j7+5pSEw05TssPmWIIoiKYhj9Gf0OCvHqQYCeICkGCmgDIFEMQBFE5SLATBEFUDBLsBEEQFSOVYGeM/TfG2PcZY6OMsZcYY+93NTCCIAgiGWk19kHO+Z2c87UAvgHgSw7GRBAEQaQglWDnnP9T6M/FAHi64RAEQRBpSR3uyBj7CoD/COBtABs133sMwGOzf77DGItWGnoPgH9MO56CQtdWTujaykmVr80oLZhxrleyGWPfBvBeyT89yTn/89D3ngCwiHO+w2aUod+f5JyvS/LbokPXVk7o2soJXZuBxs45/5jhOf8ngCMAEgl2giAIwg1po2I+GPrzAQDn0g2HIAiCSEtaG/texthKANMALgD4tRTHejblWIoMXVs5oWsrJ11/bbE2doIgCKJcUOYpQRBExSiUYK9yJitjbJAxdm72+v6MMdab95hcwRh7iDF2ljE2zRirRDQCY+wTjLHzjLEfMsa25z0eVzDG/pgx9hPG2N/lPRbXMMZuZYwdY4y9Ovs+/kbeY3IFY2wRY+xvGWOnZ69tl/b7RTLFMMZ+WiQ9Mcb+K4APc87T2O0LA2Ps4wBe5pxPMsZ+GwA451/IeVhOYIx9CDN+lj8E8HnO+cmch5QKxlgdwP8F8AsA3gTwXQAPc87/T64DcwBj7N8BeAfAn3DOfzbv8biEMfY+AO/jnH+PMfZTAE4B6K/Ic2MAFnPO32GMBQD+GsBvcM5PyL5fKI29ypmsnPOXOOeTs3+eAPCBPMfjEs75q5zzKrW2/wiAH3LO/55zfh3AnwL4pZzH5ATO+V8BuJz3OHzAOX+Lc/692f/+ZwCvAqhEcXo+wzuzfwaz/1PKx0IJdmAmk5Ux9gaAR1Dd2jP/GcBf5D0IQkkTwBuhv99ERQREt8AYWwGgD8Ar+Y7EHYyxOmNsFMBPAHyLc668tswFO2Ps24yxv5P875cAgHP+JOf8VgD7APx61uNLQ9y1zX7nSQCTmLm+0mBybRWCST6rzO6x6jDGbgZwEMDWiBWg1HDOp2YLLn4AwEcYY0pTWuat8aqcyRp3bYyxXwXwSQA/z4vk3DDA4rlVgTcB3Br6+wMAfpzTWAgLZu3PBwHs45y/mPd4fMA5H2OM/SWATwCQOsELZYqpciYrY+wTAL4A4AHO+Xje4yG0fBfABxljtzPGFgL4ZQCHch4TEcOsg/HrAF7lnH817/G4hDG2TETSMcYaAD4GjXwsWlTMQcxUL5vLZOWct/IdlRsYYz8EcBOA/zf70YkKRfx8CsDvAVgGYAzAKOd8U76jSgdj7BcBPAOgDuCPOedfyXlITmCMPQ/g5zBTAfEfAOzgnH8910E5gjH2bwH8bwBnMCNDAOCLnPNv5jcqNzDG7gTwPzDzPtYA7Oecf1n5/SIJdoIgCCI9hTLFEARBEOkhwU4QBFExSLATBEFUDBLsBEEQFYMEO0EQRMUgwU4QBFExSLATBEFUDBLsBEEQFeP/A2eX1+i0yz7HAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print(t_sne_result_gpu.shape)\n",
    "plot_tsne(t_sne_result_gpu)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "#### TSNE Sklearn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[t-SNE] Computing 31 nearest neighbors...\n",
      "[t-SNE] Indexed 1000 samples in 0.014s...\n",
      "[t-SNE] Computed neighbors for 1000 samples in 1.719s...\n",
      "[t-SNE] Computed conditional probabilities for sample 1000 / 1000\n",
      "[t-SNE] Mean sigma: 1.281465\n",
      "[t-SNE] Computed conditional probabilities in 0.246s\n",
      "[t-SNE] Iteration 50: error = 22.9653931, gradient norm = 0.0879670 (50 iterations in 0.799s)\n",
      "[t-SNE] Iteration 100: error = 22.9979153, gradient norm = 0.0761279 (50 iterations in 0.828s)\n",
      "[t-SNE] Iteration 150: error = 22.9748974, gradient norm = 0.1040474 (50 iterations in 0.847s)\n",
      "[t-SNE] Iteration 200: error = 23.1668148, gradient norm = 0.0860164 (50 iterations in 0.824s)\n",
      "[t-SNE] Iteration 250: error = 23.5420952, gradient norm = 0.0665374 (50 iterations in 0.845s)\n",
      "[t-SNE] KL divergence after 250 iterations with early exaggeration: 23.542095\n",
      "[t-SNE] Iteration 300: error = 3.1524441, gradient norm = 0.0022424 (50 iterations in 0.644s)\n",
      "[t-SNE] Iteration 350: error = 2.9878078, gradient norm = 0.0006833 (50 iterations in 0.606s)\n",
      "[t-SNE] Iteration 400: error = 2.9255419, gradient norm = 0.0003284 (50 iterations in 0.602s)\n",
      "[t-SNE] Iteration 450: error = 2.8959928, gradient norm = 0.0002248 (50 iterations in 0.601s)\n",
      "[t-SNE] Iteration 500: error = 2.8813288, gradient norm = 0.0001768 (50 iterations in 0.605s)\n",
      "[t-SNE] Iteration 550: error = 2.8726237, gradient norm = 0.0001399 (50 iterations in 0.601s)\n",
      "[t-SNE] Iteration 600: error = 2.8667474, gradient norm = 0.0001311 (50 iterations in 0.602s)\n",
      "[t-SNE] Iteration 650: error = 2.8626695, gradient norm = 0.0001437 (50 iterations in 0.606s)\n",
      "[t-SNE] Iteration 700: error = 2.8592155, gradient norm = 0.0001342 (50 iterations in 0.618s)\n",
      "[t-SNE] Iteration 750: error = 2.8566895, gradient norm = 0.0001047 (50 iterations in 0.610s)\n",
      "[t-SNE] Iteration 800: error = 2.8545871, gradient norm = 0.0001108 (50 iterations in 0.613s)\n",
      "[t-SNE] Iteration 850: error = 2.8532045, gradient norm = 0.0001128 (50 iterations in 0.610s)\n",
      "[t-SNE] Iteration 900: error = 2.8517258, gradient norm = 0.0000840 (50 iterations in 0.613s)\n",
      "[t-SNE] Iteration 950: error = 2.8504300, gradient norm = 0.0001398 (50 iterations in 0.612s)\n",
      "[t-SNE] Iteration 1000: error = 2.8497429, gradient norm = 0.0000848 (50 iterations in 0.616s)\n",
      "[t-SNE] Iteration 1050: error = 2.8486471, gradient norm = 0.0001024 (50 iterations in 0.614s)\n",
      "[t-SNE] Iteration 1100: error = 2.8473372, gradient norm = 0.0000945 (50 iterations in 0.617s)\n",
      "[t-SNE] Iteration 1150: error = 2.8464293, gradient norm = 0.0001140 (50 iterations in 0.632s)\n",
      "[t-SNE] Iteration 1200: error = 2.8458798, gradient norm = 0.0001077 (50 iterations in 0.627s)\n",
      "[t-SNE] Iteration 1250: error = 2.8452215, gradient norm = 0.0000756 (50 iterations in 0.625s)\n",
      "[t-SNE] Iteration 1300: error = 2.8445473, gradient norm = 0.0000925 (50 iterations in 0.631s)\n",
      "[t-SNE] Iteration 1350: error = 2.8440709, gradient norm = 0.0000688 (50 iterations in 0.630s)\n",
      "[t-SNE] Iteration 1400: error = 2.8436134, gradient norm = 0.0001021 (50 iterations in 0.625s)\n",
      "[t-SNE] Iteration 1450: error = 2.8429320, gradient norm = 0.0000946 (50 iterations in 0.626s)\n",
      "[t-SNE] Iteration 1500: error = 2.8426468, gradient norm = 0.0000966 (50 iterations in 0.627s)\n",
      "[t-SNE] Iteration 1550: error = 2.8425565, gradient norm = 0.0000916 (50 iterations in 0.627s)\n",
      "[t-SNE] Iteration 1600: error = 2.8422070, gradient norm = 0.0000935 (50 iterations in 0.628s)\n",
      "[t-SNE] Iteration 1650: error = 2.8416920, gradient norm = 0.0000885 (50 iterations in 0.628s)\n",
      "[t-SNE] Iteration 1700: error = 2.8411152, gradient norm = 0.0000695 (50 iterations in 0.629s)\n",
      "[t-SNE] Iteration 1750: error = 2.8410566, gradient norm = 0.0000702 (50 iterations in 0.632s)\n",
      "[t-SNE] Iteration 1800: error = 2.8408346, gradient norm = 0.0000652 (50 iterations in 0.633s)\n",
      "[t-SNE] Iteration 1850: error = 2.8400548, gradient norm = 0.0000652 (50 iterations in 0.636s)\n",
      "[t-SNE] Iteration 1900: error = 2.8397675, gradient norm = 0.0000849 (50 iterations in 0.631s)\n",
      "[t-SNE] Iteration 1950: error = 2.8396935, gradient norm = 0.0000767 (50 iterations in 0.633s)\n",
      "[t-SNE] Iteration 2000: error = 2.8391671, gradient norm = 0.0000782 (50 iterations in 0.633s)\n",
      "[t-SNE] Error after 2000 iterations: 2.839167\n",
      "CPU times: user 25.9 s, sys: 2.27 s, total: 28.2 s\n",
      "Wall time: 28 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "t_sne_result_sklearn = tsne_bhcuda.t_sne(samples=data_for_tsne, use_scikit=True, files_dir=files_dir,\n",
    "                        no_dims=2, perplexity=perplexity, eta=learning_rate, theta=theta,\n",
    "                        iterations=iterations, gpu_mem=gpu_mem, randseed=-1, verbose=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1000, 2)\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "print(t_sne_result_sklearn.shape)\n",
    "plot_tsne(t_sne_result_sklearn)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
